package com.example.demo.service.impl;

import com.example.demo.dto.ProcessNodeDTO;
import com.example.demo.entity.ProcessNode;
import com.example.demo.mapper.ProcessNodeMapper;
import com.example.demo.request.CreateProcessNodeRequest;
import com.example.demo.service.ProcessNodeService;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
//import org.slf4j.logger;
//import org.slf4j.loggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class ProcessNodeServiceImpl implements ProcessNodeService {
//    private static final logger log = loggerFactory.getlogger(ProcessNodeServiceImpl.class);

    @Autowired
    private ProcessNodeMapper processNodeMapper;

    @Autowired
    private ObjectMapper objectMapper;

    @Override
    public List<ProcessNodeDTO> getProcessNodes(Long processId) {
        //log.info("开始获取流程节点列表，processId: {}", processId);
        
        try {
            // 参数验证
            if (processId == null) {
                //log.warn("获取流程节点失败：processId为空");
                throw new IllegalArgumentException("processId不能为空");
            }
            
            // 查询流程节点
            //log.debug("正在查询流程节点，processId: {}", processId);
            List<ProcessNode> nodes = processNodeMapper.selectByProcessId(processId);
            
            if (nodes == null) {
                //log.warn("查询流程节点返回null，processId: {}", processId);
                nodes = new ArrayList<>();
            }
            
            //log.info("成功查询到流程节点数量: {}，processId: {}", nodes.size(), processId);
            
            // 转换为DTO
            List<ProcessNodeDTO> result = nodes.stream()
                    .map(this::convertToDTO)
                    .collect(Collectors.toList());
            
            //log.info("流程节点转换完成，返回DTO数量: {}，processId: {}", result.size(), processId);
            return result;
            
        } catch (Exception e) {
            //log.error("获取流程节点列表失败，processId: {}, 错误信息: {}", processId, e.getMessage(), e);
            throw e;
        }
    }

    @Override
    public ProcessNodeDTO createProcessNode(Long processId, CreateProcessNodeRequest request) {
        ProcessNode processNode = new ProcessNode();
        processNode.setProcessId(processId);
        processNode.setNodeOrder(request.getNodeOrder());
        processNode.setNodeName(request.getNodeName());
        processNode.setDepartment(request.getDepartment());
        processNode.setRole(request.getRole());
        processNode.setNodeContent(convertObjectToString(request.getNodeContent()));
        processNode.setDepartmentId(request.getDepartmentId());
        processNode.setRoleId(request.getRoleId());
        processNode.setCreatedAt(LocalDateTime.now());
        processNode.setUpdatedAt(LocalDateTime.now());

        processNodeMapper.insert(processNode);
        return convertToDTO(processNode);
    }

    @Override
    public List<ProcessNodeDTO> batchCreateProcessNodes(Long processId, List<CreateProcessNodeRequest> requests) {
        List<ProcessNode> nodes = requests.stream().map(request -> {
            ProcessNode node = new ProcessNode();
            node.setProcessId(processId);
            node.setNodeOrder(request.getNodeOrder());
            node.setNodeName(request.getNodeName());
            node.setDepartment(request.getDepartment());
            node.setRole(request.getRole());
            node.setNodeContent(convertObjectToString(request.getNodeContent()));
            node.setDepartmentId(request.getDepartmentId());
            node.setRoleId(request.getRoleId());
            node.setCreatedAt(LocalDateTime.now());
            node.setUpdatedAt(LocalDateTime.now());
            return node;
        }).collect(Collectors.toList());

        processNodeMapper.batchInsert(nodes);
        return nodes.stream()
                .map(this::convertToDTO)
                .collect(Collectors.toList());
    }

    @Override
    public ProcessNodeDTO updateProcessNode(Long processId, Long nodeId, CreateProcessNodeRequest request) {
        ProcessNode processNode = processNodeMapper.selectById(nodeId);
        if (processNode == null || !processNode.getProcessId().equals(processId)) {
            return null;
        }

        processNode.setNodeOrder(request.getNodeOrder());
        processNode.setNodeName(request.getNodeName());
        processNode.setDepartment(request.getDepartment());
        processNode.setRole(request.getRole());
        processNode.setNodeContent(convertObjectToString(request.getNodeContent()));
        processNode.setDepartmentId(request.getDepartmentId());
        processNode.setRoleId(request.getRoleId());
        processNode.setUpdatedAt(LocalDateTime.now());

        processNodeMapper.updateById(processNode);
        return convertToDTO(processNode);
    }

    @Override
    public void deleteProcessNode(Long processId, Long nodeId) {
        ProcessNode processNode = processNodeMapper.selectById(nodeId);
        if (processNode != null && processNode.getProcessId().equals(processId)) {
            processNodeMapper.deleteById(nodeId);
        }
    }

    @Override
    public ProcessNodeDTO getProcessNodeById(Long nodeId) {
        ProcessNode processNode = processNodeMapper.selectById(nodeId);
        if (processNode == null) {
            return null;
        }
        return convertToDTO(processNode);
    }

    private ProcessNodeDTO convertToDTO(ProcessNode processNode) {
        ProcessNodeDTO dto = new ProcessNodeDTO();
        dto.setId(processNode.getId());
        dto.setNodeOrder(processNode.getNodeOrder());
        dto.setNodeName(processNode.getNodeName());
        dto.setDepartment(processNode.getDepartment());
        dto.setRole(processNode.getRole());
        dto.setNodeContent(convertStringToObject(processNode.getNodeContent()));
        dto.setDepartmentId(processNode.getDepartmentId());
        dto.setRoleId(processNode.getRoleId());
        return dto;
    }

    private String convertObjectToString(Object object) {
        if (object == null) {
            return null;
        }
        try {
            return objectMapper.writeValueAsString(object);
        } catch (JsonProcessingException e) {
            throw new RuntimeException("Failed to convert object to JSON", e);
        }
    }

    private Object convertStringToObject(String json) {
        if (json == null) {
            return null;
        }
        try {
            return objectMapper.readValue(json, Object.class);
        } catch (JsonProcessingException e) {
            throw new RuntimeException("Failed to convert JSON to object", e);
        }
    }
}